package com.mail.server.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mail.commons.utils.BCryptUtil;
import com.mail.commons.utils.IpUtil;
import com.mail.commons.utils.JwtUtils;
import com.mail.commons.utils.UserHolder;
import com.mail.dubbo.api.*;
import com.mail.model.db.*;
import com.mail.model.dto.AdminPasswordDto;
import com.mail.model.vo.InfoVo;
import com.mail.model.vo.MyPage;
import com.mail.model.vo.PageResult;
import com.mail.server.common.R;
import io.netty.util.internal.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.regex.Pattern;

/**
 * @author 吕永乐
 * @date 2022/06/21 09:57
 **/
@Service
public class UmsAdminService {

	@DubboReference
	private UmsAdminApi umsAdminApi;

	@DubboReference
	private UmsAdminLoginLogApi umsAdminLoginLogApi;

	@DubboReference
	private UmsAdminRoleRelationApi umsAdminRoleRelationApi;

	@DubboReference
	private UmsRoleApi umsRoleApi;

	@DubboReference
	private UmsMenuApi umsMenuApi;

	@DubboReference
	private UmsRoleMenuRelationApi umsRoleMenuRelationApi;

	@Autowired
	private HttpServletRequest request;

	/**
	 * 用户登录
	 *
	 * @param umsAdmin
	 * @return
	 */
	public R<Object> login(UmsAdmin umsAdmin) {
		// 调用api查询用户名
		String username = umsAdmin.getUsername();
		UmsAdmin admin = umsAdminApi.getAdminByUsername(username);
		if (ObjectUtil.isEmpty(admin)) {
			return R.error("用户名不存在!");
		}
		// 判断账号是否可用
		if (!ObjectUtil.equal(1, admin.getStatus())) {
			return R.error("当前账号被禁用!");
		}
		// 判断密码是否正确
		// 将前端输入的密码加密
		String password = BCryptUtil.getPassword(umsAdmin.getPassword());
		if (!BCryptUtil.checkPassword(umsAdmin.getPassword(), password)) {
			return R.error("用户名或者密码错误!");
		}

		// 到达这一步,登录成功
		// ********保存登录日志********
		UmsAdminLoginLog adminLog = new UmsAdminLoginLog();
		// 使用工具类生成当前用户登录ip/浏览器登录类型/登录地址
		String ip = IpUtil.getIpAddress(request);
		adminLog.setIp(ip);
		adminLog.setAdminId(admin.getId());
		adminLog.setCreateTime(DateUtil.toLocalDateTime(new Date()));
		// adminLog.setAddress(IpUtil.getIpInfo(ip));
		adminLog.setUserAgent(IpUtil.getBrowserName(request));
		umsAdminLoginLogApi.saveLog(adminLog);
		// ********保存登录日志********

		// 更新最后登录时间
		// 根据 id 查询登录日志, 获取最后登录时间
		LocalDateTime lastLoginTime = umsAdminLoginLogApi.getLastLoginTime(admin.getId());
		admin.setLoginTime(lastLoginTime);
		umsAdminApi.updateLastLoginTime(admin);

		// 构造token返回值
		Map<String, Object> retMap = getTokenMap(admin);
		return R.success(retMap);
	}

	private Map<String, Object> getTokenMap(UmsAdmin admin) {
		// 生成token
		Map<String, Object> tokenMap = new HashMap<>();
		tokenMap.put("id", admin.getId());
		tokenMap.put("username", admin.getUsername());
		String token = JwtUtils.getToken(tokenMap);
		// 构造返回值
		Map<String, Object> retMap = new HashMap<>();
		retMap.put("token", token);
		retMap.put("tokenHead", "Bearer ");
		return retMap;
	}

	/**
	 * 获取当前登录用户信息
	 *
	 * @return
	 */
	public InfoVo getInfo() {
		Long userId = UserHolder.getUserId();
		// 根据 userId 查询 用户名
		UmsAdmin admin = umsAdminApi.getAdminById(userId);
		String username = admin.getUsername();
		String icon = admin.getIcon();
		//根据 adminId 查询 roleId
		List<UmsAdminRoleRelation> umsAdminRoleRelations = umsAdminRoleRelationApi.getByAdminId(userId);
		List<Long> roleIds = CollUtil.getFieldValues(umsAdminRoleRelations, "roleId", Long.class);
		// 查询角色名称
		List<UmsRole> umsRoles = umsRoleApi.getByIds(roleIds);
		List<String> roles = CollUtil.getFieldValues(umsRoles, "name", String.class);
		// 根据 roleIds 查询 menuIds
		List<UmsRoleMenuRelation> umsRoleMenuRelations = umsRoleMenuRelationApi.getByRoleIds(roleIds);
		List<Long> menuIds = CollUtil.getFieldValues(umsRoleMenuRelations, "menuId", Long.class);
		// 根据 menuIds 查询 menus
		List<UmsMenu> umsMenus = umsMenuApi.getByIds(menuIds);
		// 返回 VO 对象
		return new InfoVo(roles, icon, umsMenus, username);
	}

	/**
	 * 根据用户名或姓名分页获取用户列表 (分页查询)
	 *
	 * @param pageNum 当前页
	 * @param pageSize 每页展示条数
	 * @param keyword 搜索框关键词
	 * @return
	 */
	public MyPage<UmsAdmin> list(Long pageNum, Long pageSize, String keyword) {
		Page<UmsAdmin> admins =  umsAdminApi.getAdminByPage(pageNum, pageSize, keyword);

		return MyPage.init(admins);
	}

	/**
	 * 用户注册
	 * @param umsAdmin
	 * @return
	 */
	public R<UmsAdmin> register(UmsAdmin umsAdmin) {
		// 用户名为空,结束,返回错误信息
		if(StringUtils.isEmpty(umsAdmin.getUsername())){
			return R.success(null, "用户名不能为空!", 404);
		}
		// 密码为空,结束,返回错误信息
		if(StringUtils.isEmpty(umsAdmin.getPassword())){
			return R.success(null, "密码不能为空!", 404);
		}
		// 校验邮箱格式,如果格式错误,返回错误信息
		if(StringUtils.isNotEmpty(umsAdmin.getEmail())){
			String check = "^(\\w+([-.][A-Za-z0-9]+)*){3,18}@\\w+([-.][A-Za-z0-9]+)*\\.\\w+([-.][A-Za-z0-9]+)*$";
			if(!Pattern.matches(check, umsAdmin.getEmail())){
				return R.success(null, "邮箱格式不正确!", 404);
			}
		}
		// 判断 username 是否存在,若存在, 则返回错误信息
		UmsAdmin admin = umsAdminApi.getAdminByUsername(umsAdmin.getUsername());
		if(ObjectUtil.isNotEmpty(admin)){
			return R.success(null, "操作失败!", 500);
		}

		//走到这一步, 则可以进行注册
		// 保存数据
		umsAdmin.setCreateTime(DateUtil.toLocalDateTime(new Date()));
		umsAdmin.setPassword(BCryptUtil.getPassword(umsAdmin.getPassword()));
		umsAdminApi.save(umsAdmin);
		// 查询最新保存的数据
		UmsAdmin adminNew = umsAdminApi.getAdminByUsername(umsAdmin.getUsername());
		return R.success(adminNew, "操作成功");
	}

	/**
	 * 修改账号状态
	 * @param id 修改人id
	 * @param status 修改的状态
	 * @return
	 */
	public R<Object> updateStatus(Long id, Integer status) {
		umsAdminApi.updateStatusById(id, status);
		return R.success(null, "状态修改成功!");
	}

	/**
	 * 修改指定用户信息
	 * @param umsAdmin
	 * @return
	 */
	public R<String> update(UmsAdmin umsAdmin) {
		// 用户名为空,结束,返回错误信息
		if(StringUtils.isEmpty(umsAdmin.getUsername())){
			return R.success(null, "用户名不能为空!", 404);
		}
		// 密码为空,结束,返回错误信息
		if(StringUtils.isEmpty(umsAdmin.getPassword())){
			return R.success(null, "密码不能为空!", 404);
		}
		// 校验邮箱格式,如果格式错误,返回错误信息
		if(StringUtils.isNotEmpty(umsAdmin.getEmail())){
			String check = "^(\\w+([-.][A-Za-z0-9]+)*){3,18}@\\w+([-.][A-Za-z0-9]+)*\\.\\w+([-.][A-Za-z0-9]+)*$";
			if(!Pattern.matches(check, umsAdmin.getEmail())){
				return R.success(null, "邮箱格式不正确!", 404);
			}
		}
		umsAdminApi.update(umsAdmin);
		return R.success("修改成功!");
	}

	/**
	 * 刷新token
	 * @return
	 */
	public Map<String, Object> refreshToken() {
		// 根据id查询admin
		UmsAdmin admin = umsAdminApi.getAdminById(UserHolder.getUserId());
		Map<String, Object> tokenMap = getTokenMap(admin);
		return tokenMap;
	}

	/**
	 * 获取指定用户的角色
	 * @param adminId
	 * @return
	 */
	public List<UmsRole> getRolesInfo(Long adminId) {
		//根据 adminId 查询 roleId
		List<UmsAdminRoleRelation> umsAdminRoleRelations = umsAdminRoleRelationApi.getByAdminId(adminId);
		List<Long> roleIds = CollUtil.getFieldValues(umsAdminRoleRelations, "roleId", Long.class);
		if(CollUtil.isEmpty(roleIds)){
			return new ArrayList<>();
		}
		// 查询角色信息
		List<UmsRole> umsRoles = umsRoleApi.getByIds(roleIds);
		return umsRoles;
	}

	/**
	 * 给用户分配角色
	 * @param adminId
	 * @param roleIds
	 * @return
	 */
	public R<Integer> updateAdminRole(Long adminId, List<Long> roleIds) {
		// 根据 adminId 查询 当前用户的 roleIds
		List<UmsAdminRoleRelation> umsAdminRoleRelations = umsAdminRoleRelationApi.getByAdminId(adminId);
		// 若存在
		if(CollUtil.isNotEmpty(umsAdminRoleRelations)){
			// 首先根据adminId删除原来的roleIds
			umsAdminRoleRelationApi.removeByAdminId(adminId);
		}
		// 再批量添加新的 roleIds
		for (Long roleId : roleIds) {
			UmsAdminRoleRelation umsAdminRoleRelation = new UmsAdminRoleRelation();
			umsAdminRoleRelation.setAdminId(adminId);
			umsAdminRoleRelation.setRoleId(roleId);
			umsAdminRoleRelationApi.save(umsAdminRoleRelation);
		}
		return R.success(roleIds.size(),"操作成功!");
	}

	/**
	 * 删除指定用户信息
	 * @param adminId
	 * @return
	 */
	public R<Integer> delete(Long adminId) {
		// 删除当前用户
		umsAdminApi.remove(adminId);
		// 删除当前用户对应的角色信息
		umsAdminRoleRelationApi.removeByAdminId(adminId);
		return R.success(1, "操作成功!");
	}

	/**
	 * 获取指定用户信息
	 * @param id
	 * @return
	 */
	public UmsAdmin getUserInfo(Long id) {
		UmsAdmin admin = umsAdminApi.getAdminById(id);
		return admin;
	}

	/**
	 * 修改指定用户密码
	 * @param adminPasswordDto
	 * @return
	 */
	public R<Integer> updatePassword(AdminPasswordDto adminPasswordDto) {
		// 根据 username 查询 admin 信息
		UmsAdmin umsAdmin = umsAdminApi.getAdminByUsername(adminPasswordDto.getUsername());
		String password = umsAdmin.getPassword();
		// 与前端传来的旧密码做比较
		if (!BCryptUtil.checkPassword(adminPasswordDto.getOldPassword(), password)) {
			// 旧密码与数据库不匹配,返回错误信息
			return R.error(null, "旧密码错误", 500);
		}
		// 旧密码匹配一致,将密码修改为新密码
		umsAdmin.setPassword(BCryptUtil.getPassword(adminPasswordDto.getNewPassword()));
		umsAdminApi.updatePasswordByUsername(umsAdmin);
		return R.success(1, "操作成功!");
	}
}
